// MainFrm.cpp : implementation of the CMainFrame class
//

#include "stdafx.h"
#include "LoPlayer.h"
#include "MainFrm.h"

#include <InitGuid.h>
#include "ChildView.h"
#include "SkinWnd.h"
#include "GraphThread.h"
#include "FullscreenWnd.h"
#include "OpenFileDlg.h"
#include "openmediadata.h"
#include "..\dsutil\DSUtil.h"
#include "LanguageRes.h"
#include "LopSettings.h"
#include "VMROSD.h"
#include "..\inc\IBufferInfo.h"
#include "PlayerImpl.h"

STDAPI CreateGraphBuilder2(REFCLSID, HWND, const LOP_SETTINGS*, IGraphBuilder2**);

#ifdef _DEBUG
#define new DEBUG_NEW
#endif


// CMainFrame

IMPLEMENT_DYNAMIC(CMainFrame, CFrameWnd)

BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
	ON_WM_CREATE()
	ON_WM_DESTROY()
	ON_WM_SETFOCUS()
	ON_WM_SIZE()
	ON_WM_MOVE()
	ON_WM_CONTEXTMENU()
	ON_WM_SHOWWINDOW()
	ON_MESSAGE(WM_GRAPHNOTIFY, &CMainFrame::OnGraphNotify)
	ON_MESSAGE(WM_VIDEOSIZE, &CMainFrame::OnVideoSize)
	ON_COMMAND(ID_FILE_OPEN, &CMainFrame::OnFileOpen)
	ON_COMMAND(ID_FILE_CLOSE, &CMainFrame::OnFileClose)
	ON_COMMAND(ID_PLAY_PLAYPAUSE, &CMainFrame::OnPlayPlaypause)
	ON_COMMAND(ID_PLAY_STOP, &CMainFrame::OnPlayStop)
	ON_COMMAND(ID_NAVIGATE_BACK, &CMainFrame::OnNavigateBack)
	ON_COMMAND(ID_NAVIGATE_NEXT, &CMainFrame::OnNavigateNext)
END_MESSAGE_MAP()


// CMainFrame construction/destruction

CMainFrame::CMainFrame()
		: m_pPlayerImpl(new CPlayerImpl(this))
		, m_pwndView(new CChildView)
		, m_pSkinFrame(new CSkinWnd)
		, m_pFullscreenWnd(new CFullscreenWnd(this))
		, m_pGraphThread(NULL)
		, m_iMediaLoadState(MLS_NONE)
		, m_iPlaybackMode(COpenMediaData::PM_NONE)
		, m_pVideoWnd(NULL)
{
	// TODO: add member initialization code here

}

CMainFrame::~CMainFrame()
{
	if (m_pGraphThread && m_pGraphThread->m_hThread) {
		ASSERT(FALSE);
		::TerminateThread(m_pGraphThread->m_hThread, 0xFF);
		m_pGraphThread = NULL;
	}

}

//=============================================================================
BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)
{
	if ( !CFrameWnd::PreCreateWindow(cs) )
		return FALSE;
	// TODO: Modify the Window class or styles here by modifying
	//  the CREATESTRUCT cs

	cs.dwExStyle &= ~WS_EX_CLIENTEDGE;
	cs.lpszClass = AfxRegisterWndClass(CS_DBLCLKS | CS_VREDRAW | CS_HREDRAW,
	                                   ::LoadCursor(NULL, IDC_ARROW),
	                                   (HBRUSH) ::GetStockObject(BLACK_BRUSH),
	                                   ::LoadIcon(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDR_MAINFRAME)));

	return TRUE;
}

//=============================================================================
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
	if (CFrameWnd::OnCreate(lpCreateStruct) == -1)
		return -1;

	SetMenu(NULL); // remove main menu

	// load skin script
	TCHAR szPath[MAX_PATH] = {0};
	::GetModuleFileName(AfxGetInstanceHandle(), szPath, _MAX_PATH);
	::PathRemoveFileSpec (szPath);
	::PathRemoveBackslash (szPath);
	::PathRemoveFileSpec (szPath);
	::PathAppend (szPath, _T("skins\\asset\\"));
	if (!m_pSkinFrame->LoadSkin(this, szPath, _T("MainFrame"))) {
		ASSERT(!"Failed to load skin!\n");
		return -1;
	}

	// create a view to occupy the client area of the frame
	if (!m_pwndView->Create(this, m_pSkinFrame->GetLogImage(), m_pSkinFrame->GetBackgroundColor())) {
		TRACE0("Failed to create view window\n");
		return -1;
	}

	// thread
	m_pGraphThread = AfxBeginThread(RUNTIME_CLASS(CGraphThread));
	if (m_pGraphThread) {
		m_pGraphThread->PostThreadMessage(CGraphThread::TM_FRAME, 0, (LPARAM)this);
	}

	return 0;
}

//=============================================================================
void CMainFrame::OnDestroy()
{
	CFrameWnd::OnDestroy();

	// TODO: Add your message handler code here
	if (m_pGraphThread) {
		do 		{
			m_pGraphThread->PostThreadMessage(WM_QUIT, 0, 0);
		} while (::WaitForSingleObject(m_pGraphThread->m_hThread, 1) == WAIT_TIMEOUT);
		m_pGraphThread = NULL;
	}

}


// CMainFrame diagnostics

#ifdef _DEBUG
void CMainFrame::AssertValid() const
{
	CFrameWnd::AssertValid();
}

void CMainFrame::Dump(CDumpContext& dc) const
{
	CFrameWnd::Dump(dc);
}

#endif //_DEBUG


// CMainFrame message handlers

void CMainFrame::OnSetFocus(CWnd* /*pOldWnd*/)
{
	// forward focus to the view window
	// m_pwndView->SetFocus();
}

BOOL CMainFrame::OnCmdMsg(UINT nID, int nCode, void* pExtra, AFX_CMDHANDLERINFO* pHandlerInfo)
{
	// let the view have first crack at the command
	if (m_pwndView->OnCmdMsg(nID, nCode, pExtra, pHandlerInfo))
		return TRUE;

	// otherwise, do default handling
	return CFrameWnd::OnCmdMsg(nID, nCode, pExtra, pHandlerInfo);
}

//=============================================================================
BOOL CMainFrame::OnWndMsg(UINT message, WPARAM wParam, LPARAM lParam, LRESULT* pResult)
{
	// TODO: Add your specialized code here and/or call the base class
	if (m_pSkinFrame && m_pSkinFrame->OnWndMsg(message, wParam, lParam, pResult))
		return TRUE;

	return CFrameWnd::OnWndMsg(message, wParam, lParam, pResult);
}

//=============================================================================
void CMainFrame::OnSize(UINT nType, int cx, int cy)
{
	CFrameWnd::OnSize(nType, cx, cy);

	// TODO: Add your message handler code here
	ResetClientPos();
}

//=============================================================================
void CMainFrame::OnMove(int x, int y)
{
	CFrameWnd::OnMove(x, y);

	// TODO: Add your message handler code here
	ResetClientPos();
}

//=============================================================================
void CMainFrame::ResetClientPos(void)
{
	if (m_pwndView->GetSafeHwnd()) {
		CRect rectFrame;

		GetWindowRect(rectFrame);
		const CRect& rectClient = m_pSkinFrame->GetClientRect();

		m_pwndView->MoveWindow(rectFrame.left + rectClient.left, rectFrame.top + rectClient.top,
		                       rectClient.Width(), rectClient.Height());

		//  [6/17/2008 Dean]
		MoveVideoWindow();
	}
}

//=============================================================================
void CMainFrame::OnContextMenu(CWnd* /*pWnd*/, CPoint point)
{
	if (point.x == -1 && point.y == -1) {
		//keystroke invocation
		CRect rect;
		GetClientRect(rect);
		ClientToScreen(rect);

		point = rect.TopLeft();
		point.Offset(5, 5);
	}
	CMenu menu;
	VERIFY(menu.LoadMenu(IDR_MENUPOP));

	CMenu* pPopup = menu.GetSubMenu(0);
	ASSERT(pPopup != NULL);

	pPopup->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON, point.x, point.y, this);
}

//=============================================================================
void CMainFrame::OnShowWindow(BOOL bShow, UINT nStatus)
{
	CFrameWnd::OnShowWindow(bShow, nStatus);

	// TODO: Add your message handler code here
	m_pwndView->ShowWindow(bShow ? SW_SHOW : SW_HIDE);
}

//=============================================================================
void CMainFrame::OnFileOpen()
{
	CString strFilter;
	CStringArray asMask;

	AfxGetAppSettings().GetFormats().GetFilter(strFilter, asMask);
	COpenFileDlg dlg(strFilter, asMask, this);
	if (IDOK == dlg.DoModal()) {
		CStringList fns;
		POSITION pos = dlg.GetStartPosition();
		while (pos) fns.AddTail(dlg.GetNextPathName(pos));

		bool fMultipleFiles = false;

		if (fns.GetCount() > 1
		        || fns.GetCount() == 1
		        && (fns.GetHead()[fns.GetHead().GetLength()-1] == '\\'
		            || fns.GetHead()[fns.GetHead().GetLength()-1] == '*')) {
			fMultipleFiles = true;
		}

		m_pVideoWnd = m_pwndView;
		m_pPlayerImpl->PlayMovieInWindow(fns.GetHead(), m_pVideoWnd->GetSafeHwnd());
	}
}

//=============================================================================
void CMainFrame::OnFileClose()
{
	// TODO: Add your command handler code here
	m_pPlayerImpl->Close();
}

//=============================================================================
BOOL CMainFrame::CreateFullScreenWindow()
{
	return m_pFullscreenWnd->CreateFullWnd() ;
}

//=============================================================================
void CMainFrame::OnPlayPlaypause()
{
	// TODO: Add your command handler code here
	m_pPlayerImpl->Pause();
}

//=============================================================================
void CMainFrame::OnPlayStop()
{
	// TODO: Add your command handler code here
	m_pPlayerImpl->Stop();
}

//=============================================================================
void CMainFrame::OnNavigateBack()
{
	// TODO: Add your command handler code here
}

//=============================================================================
void CMainFrame::OnNavigateNext()
{
	// TODO: Add your command handler code here
}

//=============================================================================
void CMainFrame::MoveVideoWindow(void)
{
	if (m_pVideoWnd->GetSafeHwnd()){
		ASSERT(m_pVideoWnd);
		CRect rect;
		m_pVideoWnd->GetClientRect(rect);

		m_pPlayerImpl->SetVideoWindowPos(rect);
	}
}

//=============================================================================
LRESULT CMainFrame::OnGraphNotify( WPARAM, LPARAM lParam)
{
	return m_pPlayerImpl->HandleGraphEvent(lParam);
}

//=============================================================================
LRESULT CMainFrame::OnVideoSize( WPARAM, LPARAM lParam )
{
	if (!m_pVideoWnd->GetSafeHwnd())
		return -1;

	ASSERT(m_pVideoWnd);

	const int cxVideo = GET_X_LPARAM(lParam);
	const int cyVideo = GET_Y_LPARAM(lParam);

	CRect rect;
	m_pVideoWnd->GetClientRect(rect);
	int cx = cxVideo - rect.Width();
	int cy = cyVideo - rect.Height();
	if (cx || cy){
		CRect rtFrame;
		GetWindowRect(rtFrame);
		cx += rtFrame.Width();
		cy += rtFrame.Height();
		SetWindowPos(NULL, 0, 0, cx, cy, SWP_NOMOVE);
		CenterWindow ();
		MoveVideoWindow ();
	}

	return 0L;
}
